package com.example.myapplication.analysis

import com.example.myapplication.model.StockPrice
import com.example.myapplication.model.TechnicalIndicators
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
import kotlin.math.sqrt

/**
 * 技术分析计算器
 * 实现各种技术指标计算
 */
class TechnicalAnalyzer {
    
    /**
     * 计算所有技术指标
     */
    fun calculateIndicators(prices: List<StockPrice>): TechnicalIndicators {
        if (prices.isEmpty()) return TechnicalIndicators()
        
        val closes = prices.map { it.close }
        val volumes = prices.map { it.volume.toDouble() }
        val highs = prices.map { it.high }
        val lows = prices.map { it.low }
        
        return TechnicalIndicators(
            ma5 = calculateMA(closes, 5),
            ma10 = calculateMA(closes, 10),
            ma20 = calculateMA(closes, 20),
            ma60 = calculateMA(closes, 60),
            macd = calculateMACD(closes)?.macd,
            macdSignal = calculateMACD(closes)?.signal,
            macdHistogram = calculateMACD(closes)?.histogram,
            rsi = calculateRSI(closes, 14),
            k = calculateKDJ(highs, lows, closes)?.k,
            d = calculateKDJ(highs, lows, closes)?.d,
            j = calculateKDJ(highs, lows, closes)?.j,
            bollUpper = calculateBollinger(closes)?.upper,
            bollMiddle = calculateBollinger(closes)?.middle,
            bollLower = calculateBollinger(closes)?.lower,
            volumeMA5 = calculateMA(volumes, 5),
            volumeMA10 = calculateMA(volumes, 10)
        )
    }
    
    /**
     * 计算移动平均线（MA）
     */
    fun calculateMA(data: List<Double>, period: Int): Double? {
        if (data.size < period) return null
        return data.takeLast(period).average()
    }
    
    /**
     * 计算指数移动平均线（EMA）
     */
    fun calculateEMA(data: List<Double>, period: Int): Double? {
        if (data.size < period) return null
        
        val multiplier = 2.0 / (period + 1)
        var ema = data.take(period).average()
        
        for (i in period until data.size) {
            ema = (data[i] - ema) * multiplier + ema
        }
        
        return ema
    }
    
    /**
     * 计算MACD（Moving Average Convergence Divergence）
     */
    fun calculateMACD(prices: List<Double>): MACDResult? {
        if (prices.size < 35) return null  // 至少需要26+9=35个数据点
        
        val ema12 = calculateEMA(prices, 12) ?: return null
        val ema26 = calculateEMA(prices, 26) ?: return null
        val macd = ema12 - ema26
        
        // 计算Signal线（MACD的9日EMA）
        val macdHistory = mutableListOf<Double>()
        for (i in 26 until minOf(prices.size, 100)) {  // 限制循环范围，避免越界
            val e12 = calculateEMA(prices.take(i + 1), 12) ?: continue
            val e26 = calculateEMA(prices.take(i + 1), 26) ?: continue
            macdHistory.add(e12 - e26)
        }
        
        if (macdHistory.size < 9) return null  // 确保有足够数据计算信号线
        
        val signal = calculateEMA(macdHistory, 9) ?: return null
        val histogram = macd - signal
        
        return MACDResult(macd, signal, histogram)
    }
    
    /**
     * 计算RSI（Relative Strength Index）
     */
    fun calculateRSI(prices: List<Double>, period: Int = 14): Double? {
        if (prices.size <= period) return null
        
        var gains = 0.0
        var losses = 0.0
        
        // 修复索引计算，避免越界
        val startIndex = prices.size - period - 1
        if (startIndex < 0) return null
        
        for (i in 0 until period) {
            val currentIndex = startIndex + i + 1
            val prevIndex = startIndex + i
            
            if (currentIndex >= prices.size || prevIndex < 0) continue
            
            val change = prices[currentIndex] - prices[prevIndex]
            if (change > 0) gains += change
            else losses += abs(change)
        }
        
        val avgGain = gains / period
        val avgLoss = losses / period
        
        if (avgLoss == 0.0) return 100.0
        
        val rs = avgGain / avgLoss
        return 100.0 - (100.0 / (1.0 + rs))
    }
    
    /**
     * 计算KDJ指标
     */
    fun calculateKDJ(highs: List<Double>, lows: List<Double>, closes: List<Double>, period: Int = 9): KDJResult? {
        if (closes.size < period) return null
        
        val recentHighs = highs.takeLast(period)
        val recentLows = lows.takeLast(period)
        val currentClose = closes.last()
        
        val highestHigh = recentHighs.maxOrNull() ?: return null
        val lowestLow = recentLows.minOrNull() ?: return null
        
        val rsv = if (highestHigh == lowestLow) 50.0
        else ((currentClose - lowestLow) / (highestHigh - lowestLow)) * 100
        
        // 简化计算，实际应该使用平滑因子
        val k = rsv * 1.0 / 3.0 + 50.0 * 2.0 / 3.0
        val d = k * 1.0 / 3.0 + 50.0 * 2.0 / 3.0
        val j = 3 * k - 2 * d
        
        return KDJResult(k, d, j)
    }
    
    /**
     * 计算布林带（Bollinger Bands）
     */
    fun calculateBollinger(prices: List<Double>, period: Int = 20, stdDev: Double = 2.0): BollingerResult? {
        if (prices.size < period) return null
        
        val recentPrices = prices.takeLast(period)
        val middle = recentPrices.average()
        
        val variance = recentPrices.map { (it - middle).pow(2) }.average()
        val standardDeviation = sqrt(variance)
        
        val upper = middle + stdDev * standardDeviation
        val lower = middle - stdDev * standardDeviation
        
        return BollingerResult(upper, middle, lower)
    }
    
    /**
     * 计算波动率
     */
    fun calculateVolatility(prices: List<Double>, period: Int = 14): Double? {
        if (prices.size < period + 1) return null
        
        val returns = mutableListOf<Double>()
        for (i in 1 until prices.size) {
            returns.add((prices[i] - prices[i - 1]) / prices[i - 1])
        }
        
        val mean = returns.takeLast(period).average()
        val variance = returns.takeLast(period).map { (it - mean).pow(2) }.average()
        
        return sqrt(variance) * 100 // 返回百分比
    }
}

data class MACDResult(val macd: Double, val signal: Double, val histogram: Double)
data class KDJResult(val k: Double, val d: Double, val j: Double)
data class BollingerResult(val upper: Double, val middle: Double, val lower: Double)

